﻿using JESAI.EventBus.Executors;
using JESAI.EventBus.Monitors;
using JESAI.EventBus.PublishManagers;
using JESAI.EventBus.SubscribeManagers;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Channels;
using System.Threading.Tasks;

namespace JESAI.EventBus.Builders
{
    public sealed class EventBusOptionsBuilder
    {
        public int MaxChannelCapacity = 3000;

        public BoundedChannelFullMode BoundedChannelFullMode = BoundedChannelFullMode.Wait;

        /// <summary>
        /// 未察觉任务异常事件处理程序
        /// </summary>
        public EventHandler<Exception> UnhandleException { get; set; }

        /// <summary>
        /// 是否启用日志记录
        /// </summary>
        public bool EnabledLogOut { get; set; } = true;


        private readonly List<Type> _eventSubscribers = new();

        private Type _eventPublishManager;

        private Type _eventBusMonitor;

        private Type _customEventHandExecutor;

        private Type _eventSubscribeManager;

        public EventBusOptionsBuilder AddSubscriber<TEventSubscriber>()
            where TEventSubscriber : class, IEventSubscriber
        {
            _eventSubscribers.Add(typeof(TEventSubscriber));
            return this;
        }

        public EventBusOptionsBuilder AddSubscribers(params Assembly[] assemblies)
        {
            if (assemblies == null || assemblies.Length == 0)
            {
                throw new InvalidOperationException("The assemblies can be not null or empty.");
            }

            var subscribers = assemblies.SelectMany(ass =>
                  ass.GetExportedTypes()
                     .Where(t => t.IsPublic && t.IsClass && !t.IsInterface && !t.IsAbstract && typeof(IEventSubscriber).IsAssignableFrom(t)));

            foreach (var subscriber in subscribers)
            {
                _eventSubscribers.Add(subscriber);
            }

            return this;
        }

        public EventBusOptionsBuilder AddSubscriber(Type eventSubscriberType)
        {
            // 类型检查
            if (!typeof(IEventSubscriber).IsAssignableFrom(eventSubscriberType) || eventSubscriberType.IsInterface) throw new InvalidOperationException("The <eventSubscriberType> is not implement the IEventSubscriber interface.");

            _eventSubscribers.Add(eventSubscriberType);
            return this;
        }

        public EventBusOptionsBuilder ReplacePublisher<TEventPublisher>()
       where TEventPublisher : class, IEventPublishManager
        {
            _eventPublishManager = typeof(TEventPublisher);
            return this;
        }

        internal void Build(IServiceCollection services)
        {
            // 注册事件订阅者
            foreach (var eventSubscriber in _eventSubscribers)
            {
                services.AddSingleton(typeof(IEventSubscriber), eventSubscriber);
            }

            // 替换事件发布者
            if (_eventPublishManager != default)
            {
                services.Replace(ServiceDescriptor.Singleton(typeof(IEventPublishManager), _eventPublishManager));
            }

            // 替换事件存储器
            if (_eventSubscribeManager != default)
            {
                services.Replace(ServiceDescriptor.Singleton(_eventSubscribeManager));
            }

            // 注册事件监视器
            if (_eventBusMonitor != default)
            {
                services.AddSingleton(typeof(IEventBusMonitor), _eventBusMonitor);
            }

            // 注册事件执行器
            if (_customEventHandExecutor != default)
            {
                services.AddSingleton(typeof(ICustomEventHandExecutor), _customEventHandExecutor);
            }
        }
    }
}
